package rpg.resource
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.events.Event;
	import flash.events.ProgressEvent;
	import flash.events.TimerEvent;
	import flash.media.Sound;
	import flash.system.ApplicationDomain;
	import flash.utils.ByteArray;
	import flash.utils.Dictionary;
	import flash.utils.Timer;

	import rpg.Utils.Log;
	import rpg.data.ProgressInfo;
	import rpg.data.ResData;

	/**
	 * 批量下载
	 * @author hyy
	 *
	 */
	public class Resources
	{
		/**
		 * 总共需要加载的数量
		 */
		private var loardCount : int;
		/**
		 * 当前完成加载的数量
		 */
		private var resIndex : int;
		/**
		 * 加载器
		 */
		private var resources : Array;
		/**
		 * 进度条
		 */
		private var progressInfo : ProgressInfo;
		/**
		 * 加载完毕返回函数
		 */
		private var returnFun : Function;
		/**
		 * 下载后的数据
		 */
		private var lib : Dictionary;
		/**
		 * 是否锁定下载
		 */
		private var lock : Boolean;
		/**
		 * 单例
		 */
		private static var instance : Resources;

		public function Resources()
		{
		}

		public static function getInstance() : Resources
		{
			if(instance == null)
			{
				instance = new Resources();
				instance.init();
			}
			return instance;
		}


		private function init() : void
		{
			resources = [];
			lib = new Dictionary();
			progressInfo = new ProgressInfo();
		}

		/**
		 * 重置数据
		 *
		 */
		private function reset() : void
		{
			loardCount = 0;
			resIndex = 0;
			lock = false;
			for each(var resource : Resource in resources)
				resource.destory();
			//lib = new Dictionary();
			resources.length = 0;


		}

		/**
		 * 记录需要加载的地址
		 * @param data
		 *
		 */
		public function add(resData : ResData) : void
		{
			var res : Resource = createResource(resData);
			resources.push(res);
		}

		/**
		 * 根据一些参数,生成 ResourceData,然后记录数据
		 * @param url
		 * @param type
		 * @param priority
		 * @param version
		 *
		 */
		public function addData(url : String , type : String , priority : int = 0 , version : int = 0) : void
		{
			var resData : ResData = new ResData(url , type , priority , version);
			add(resData);
		}

		/**
		 * 根据data,创建所对应的资源下载器
		 * @param resData
		 * @return
		 *
		 */
		public function createResource(resData : ResData) : Resource
		{
			var res : Resource;
			var url : String = resData.url + "?v=" + resData.version;
			switch(resData.type)
			{
				case ResData.IMAGE:
					res = new IMGResource(url , onSyncComplete);
					break;
				case ResData.MP3:
					res = new MP3Resource(url , onSyncComplete);
					break;
				case ResData.SWF:
					res = new SWFResource(url , onSyncComplete);
					break;
				case ResData.TEXT:
					res = new TEXTResource(url , onSyncComplete);
					break;
				case ResData.XML:
					res = new XMLResource(url , onSyncComplete);
					break;
				default:
					res = new TEXTResource(url , onSyncComplete);
					break;
			}
			return res;
		}

		/**
		 * 批量加载
		 *
		 */
		public function startLoad(returnFun : Function = null) : void
		{
			if(lock)
			{
				Log.print("正在加载中....")
				return;
			}
			for each(var resource : Resource in resources)
				resource.load();
			lock = true;
			loardCount = resources.length;
			this.returnFun = returnFun;
		}

		/**
		 * 并发加载完成
		 *
		 */
		private function onSyncComplete(res : Resource) : void
		{
			resIndex++;
			saveLib(res);
			if(loardCount > resIndex)
			{
				return;
			}
			if(returnFun != null)
			{
				returnFun(this);
				returnFun = null;
			}
			lock = false;
			loadNext();
			reset();
		}

		/**
		 * 保存数据
		 * 图片和swf加载完后必须马上使用,否者就会销毁
		 * 只会保存文本,和xml
		 * @param resource
		 *
		 */
		private function saveLib(resource : Resource) : void
		{
			var url : String = parseResUrl(resource.url);
			if(resource is IMGResource)
				this.lib[url] = IMGResource(resource).bitmapData;
			else if(resource is MP3Resource)
				this.lib[url] = MP3Resource(resource).sound;
			else if(resource is TEXTResource)
				this.lib[url] = TEXTResource(resource).byteArray;
			else if(resource is XMLResource)
				this.lib[url] = XMLResource(resource).xml;
		}

		public function getXml(resName : String) : XML
		{
			resName += ".xml";
			return lib[resName] as XML;
		}

		public function getByteArray(resName : String) : ByteArray
		{
			return lib[resName] as ByteArray;
		}

		public function getData(resName : String) : String
		{
			resName += ".txt";
			return lib[resName].toString();
		}

		public function getMp3(resName : String) : Sound
		{
			resName += ".mp3";
			return lib[resName] as Sound;
		}

		public function getImg(resName : String) : BitmapData
		{
			return lib[resName] as BitmapData;
		}

		/**
		 * 获取加载类中资源
		 * @param resName
		 * @return
		 *
		 */
		public function getClass(resName : String) : Class
		{
			if(resName == "")
				return null;
			for each(var resource : Resource in resources)
			{
				if(resource is SWFResource)
				{
					if(SWFResource(resource).appDomain.hasDefinition(resName))
					{
						return SWFResource(resource).getAssetClass(resName);
					}
				}
			}
			return null;
		}

		/**
		 * 解析地址,比如..res/role/角色.xml?v='5'  变成角色.xml
		 * @param url
		 * @return
		 *
		 */
		private function parseResUrl(url : String) : String
		{
			url = url.split("?v=")[0].toString().split("/").pop();
			return url;
		}

		/**
		 * 加载进度
		 * @param evt
		 *
		 */
		private function onProgressEvent(evt : ProgressEvent) : void
		{
			progressInfo.bytesLoaded = 0;
			progressInfo.bytesTotal = 0;
			for each(var resource : Resource in resources)
			{
				progressInfo.bytesTotal += resource.bytesTotal;
				progressInfo.bytesLoaded += resource.bytesLoaded;
			}
		}

		/**
		 * 预加载的加载信息记录
		 */
		private var resDataArray : Array = [];
		/**
		 * 预加载是否在加载中
		 */
		private var isPreloading : Boolean = false;

		/**
		 * 后台加载,如果有批量加载的话,后台加载则会暂停
		 * 是线性加载,防止过多加载,造成游戏卡
		 * @return
		 * priority 数值越大,越先加载
		 * args加载成功后返回的函数,可以是多个
		 */
		public function preload(url : String , type : String , priority : Number = 0 , returnFun : Function = null) : Resource
		{
			var data : Object = getPreloadResDataByUrl(url);
			if(data)
			{
				var funs : Array = data["returnFun"];
				var index : int = funs.indexOf(returnFun);
				if(index == -1)
					funs.push(returnFun);
				return data["res"];
			}
			//Log.print("正在加载:" , url);
			var res : Resource;
			switch(type)
			{
				case ResData.IMAGE:
					res = new IMGResource(url , onDownComplete);
					break;
				case ResData.MP3:
					res = new MP3Resource(url , onDownComplete);
					break;
				case ResData.SWF:
					res = new SWFResource(url , onDownComplete);
					break;
				case ResData.TEXT:
					res = new TEXTResource(url , onDownComplete);
					break;
				case ResData.XML:
					res = new XMLResource(url , onDownComplete);
					break;
			}
			data = {};
			data.url = url;
			data.priority = priority;
			data["res"] = res;
			data["returnFun"] = [returnFun];
			resDataArray.push(data);
			loadNext();
			return res;
		}

		private function onDownComplete(res : Resource) : void
		{
			var index : int = getPreloadIndexByUrl(res.url);
			if(index == -1)
			{
				Log.warning("加载资源错误");
				return;
			}
			var data : Object = resDataArray[index];
			var funs : Array = data["returnFun"]

			resDataArray.splice(index , 1);
			isPreloading = false;
			loadNext();
			for each(var fun : Function in funs)
			{
				if(fun != null)
					fun(res);
			}
			funs.length = 0;
			funs = null;
			Resource(data["res"]).destory();
			delete data["res"];
			delete data["returnFun"];
		}

		/**
		 * 加载下一个
		 *
		 */
		private function loadNext() : void
		{
			if(lock)
				return;
			if(isPreloading)
				return;
			if(resDataArray.length == 0)
				return;
			resDataArray.sortOn("priority" , Array.NUMERIC | Array.DESCENDING);
			isPreloading = true;
			resDataArray[0].res.load();
		}

		/**
		 * 获得预加载的信息所索引
		 *
		 */
		private function getPreloadIndexByUrl(url : String) : int
		{
			var len : int = resDataArray.length;
			for(var i : int = 0 ; i < len ; i++)
			{
				var data : Object = resDataArray[i];
				if(data.url == url)
				{
					return i;
				}
			}
			return -1;
		}

		/**
		 * 获得预加载的信息
		 *
		 */
		public function getPreloadResDataByUrl(url : String) : Object
		{
			var index : int = getPreloadIndexByUrl(url);
			if(index == -1)
				return null
			else
				return resDataArray[index];
		}

		public function getProgress() : ProgressInfo
		{
			return progressInfo;
		}
	}
}